#! /usr/bin/env perl

use strict;
use warnings;

use Cwd;
use Getopt::Std;
use File::Basename;

use VCtools::Base;
use VCtools::Common;


our $BINDIR = DEBUG ? dirname($0) : VCtools::VCTOOLS_BINDIR;


my $opts = {};
getopts('pb', $opts);


# just calculate new $PATH and get out
if (defined $opts->{p})
{
	# return adjusted path
	my @addpath = ( $BINDIR, VCtools::SUBVERSION_BINDIR );

	# as newgrp will occasionally trash the PATH, provide a reasonable default JIC
	my @path = split(':', $ENV{PATH} ? $ENV{PATH} : '/bin:/usr/bin:/usr/local/bin');
	if ($path[-1] eq ".")
	{
		splice @path, -1, 0, @addpath;
	}
	else
	{
		@path = (@path, @addpath);
	}

	print join(':', @path);
	exit;
}


print STDERR "controlling shell var is $ENV{VCTOOLS_SHELL}\n" if DEBUG >= 2;
print STDERR "current PATH is $ENV{PATH}\n" if DEBUG >= 3;

if ($ENV{VCTOOLS_SHELL} and $ENV{VCTOOLS_SHELL} =~ /^proj:(.*)$/)
{
	VCtools::fatal_error("already in project $1!") if $1 eq $ARGV[0];

	# trying to go from one vcshell to another; that's okay as long as they confirm
	# NOTE! if you set your vcshell alias to exec, you better unset $VCTOOLS_SHELL first
	# otherwise, answering no below will leave you in bad shape
	VCtools::prompt_to_continue("switching from project $1 to project $ARGV[0]");
	delete $ENV{VCTOOLS_SHELL};
}

# being called initially from alias vcshell
if (not exists $ENV{VCTOOLS_SHELL} or $ENV{VCTOOLS_SHELL} =~ /^proj:/ or $ENV{VCTOOLS_SHELL} eq 'git')
{
	# are we going to transmogrify ourselves into vbuild?
	my $buildit = exists $opts->{b};

	my $project;
	if ($buildit)
	{
		# if no args, or if final arg starts with a dash (ie, is a switch), just call vbuild right here
		unless (@ARGV and $ARGV[-1] !~ /^-/)
		{
			my $vbuild = "$BINDIR/vbuild";
			exec $vbuild, @ARGV;
		}

		$project = $ARGV[-1];
		# pass args through to next incarnation
		$buildit = join(' ', @ARGV);
		print STDERR "gonna buildit: $buildit\n" if DEBUG >= 4;
	}
	elsif ($ARGV[0])
	{
		$project = $ARGV[0];
		my $pdir = VCtools::project_dir($project);
		unless (-d $pdir)
		{
			error("no such directory $pdir");
		}
		print STDERR "start dir $pdir\n" if DEBUG >= 3;
		#$ENV{VCTOOLS_SHELL_STARTDIR} = $pdir;
		chdir $pdir;
	}
	else
	{
		# no argument; use current directory
		my $pwd = getcwd();
		if ($pwd eq VCtools::WORKING_DIR)
		{
			# we're in the root of the personal testing tree
			# but we don't know which group to choose, because different
			# projects underneath here might have different groups
			# so bitch about it and get out
			error("don't know which project you want to work with\n"
					. "   (specify project name or cd to project dir)");
		}
		elsif (substr($pwd, 0, length(VCtools::WORKING_DIR))
				ne VCtools::WORKING_DIR)
		{
			# not even in the right tree at all
			error("current dir not part of personal testing tree\n"
					. "   (specify project name or cd into tree)");
		}

		# so we're somewhere underneath a particular project
		$project = VCtools::parse_vc_file($pwd)
				or error("can't figure out project of $pwd");
	}
	print STDERR "passed through arg checking\n" if DEBUG >= 5;

	# now get the group for the discovered project
	my $group = VCtools::project_group($project);
	print STDERR "got project group $group\n" if DEBUG >= 4;

	# crude but hopefully effective method to determine whether
	# we actually can newgrp to this group
	if (`id | fgrep $group` =~ /^\s*$/)
	{
		error("you are not a member of $group");
	}

	$ENV{VCTOOLS_SHELL} = $buildit ? "b:$buildit"
			: VCtools::get_proj_directive($project, 'VCSystem') eq 'git' ? "git" : "proj:$project";
	print STDERR "about to newgrp to $group with shellvar $ENV{VCTOOLS_SHELL} for proj $project, which has VC system: ",
			VCtools::get_proj_directive($project, 'VCSystem'), "\n" if DEBUG >= 4;
	exec("newgrp", $group) or error("cannot execute newgrp");
}
# being called by newgrp, but originally came from vbuild alias
elsif ($ENV{VCTOOLS_SHELL} =~ /^b:(.*)$/)
{
	# turn command line string back into individual args
	my @args = split(' ', $1);

	$ENV{VCTOOLS_SHELL} = "build:$args[-1]";
	chdir VCtools::WORKING_DIR;

	$ENV{PATH} .= ":" . VCtools::SUBVERSION_BINDIR;
	my $vbuild = "$BINDIR/vbuild";
	print STDERR "about to call $vbuild with @args\n" if DEBUG >= 3;
	exec $vbuild, @args;
}
# this should never happen, theoretically
else
{
	error("unknown value for shell var: $ENV{VCTOOLS_SHELL}");
}


sub error
{
	my $me = $0;
	$me =~ s@^.*/@@;

	print STDERR "$me: $_[0]\n";
	delete $ENV{VCTOOLS_SHELL};
	unless (exec $ENV{SHELL})
	{
		# JIC something goes wrong
		print STDERR "$me: catastrophic error (can't start $ENV{SHELL})\n";
		exit(-1);
	}
}
